﻿// Copyright (c) 2020-2022 百小僧, Baiqian Co.,Ltd.
// Furion is licensed under Mulan PSL v2.
// You can use this software according to the terms and conditions of the Mulan PSL v2.
// You may obtain a copy of Mulan PSL v2 at:
//             https://gitee.com/dotnetchina/Furion/blob/master/LICENSE
// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
// See the Mulan PSL v2 for more details.

using System;
using System.Collections.Concurrent;
using System.Linq;
using System.Reflection;

namespace Anno.Const
{
    /// <summary>
    /// 常量、公共方法配置类
    /// </summary>
    public static class Penetrates
    {
        /// <summary>
        /// 分组分隔符
        /// </summary>
        public const string GroupSeparator = "@";
        /// <summary>
        /// 被舍弃的控制器名称前后缀
        /// </summary>
        public static string[] AbandonControllerAffixes { get; set; }

        /// <summary>
        /// 被舍弃的行为名称前后缀
        /// </summary>
        public static string[] AbandonActionAffixes { get; set; }

        /// <summary>
        /// 请求动词映射字典
        /// </summary>
        public static ConcurrentDictionary<string, string> VerbToHttpMethods { get; private set; }

        /// <summary>
        /// 控制器排序集合
        /// </summary>
        public static ConcurrentDictionary<string, int> ControllerOrderCollection { get; set; }

        /// <summary>
        /// 构造函数
        /// </summary>
        static Penetrates()
        {
            ControllerOrderCollection = new ConcurrentDictionary<string, int>();

            VerbToHttpMethods = new ConcurrentDictionary<string, string>
            {
                ["post"] = "POST",
                ["add"] = "POST",
                ["create"] = "POST",
                ["insert"] = "POST",
                ["submit"] = "POST",

                ["get"] = "GET",
                ["find"] = "GET",
                ["fetch"] = "GET",
                ["query"] = "GET",
                ["getlist"] = "GET",
                ["getall"] = "GET",

                ["put"] = "PUT",
                ["update"] = "PUT",

                ["delete"] = "DELETE",
                ["remove"] = "DELETE",
                ["clear"] = "DELETE",

                ["patch"] = "PATCH"
            };

            IsApiControllerCached = new ConcurrentDictionary<Type, bool>();

            AbandonControllerAffixes = new string[]
           {
                    "AppServices",
                    "AppService",
                    "ApiController",
                    "Controller",
                    "Services",
                    "Service",
                    "Module","Modules"
           };
            AbandonActionAffixes = new string[]
            {
                "Async"
            };
        }

        /// <summary>
        /// <see cref="IsApiController(Type)"/> 缓存集合
        /// </summary>
        private static readonly ConcurrentDictionary<Type, bool> IsApiControllerCached;

        /// <summary>
        /// 获取接口/服务方法前缀
        /// </summary>
        /// <param name="method"></param>
        /// <returns></returns>
        public static string GetRoutePrefix(this MethodInfo method)
        {
            if (method == null) return "";
            var cab = method.GetCustomAttribute<RoutePrefixAttribute>();
            if (cab != null && !string.IsNullOrWhiteSpace(cab.Template))
                return cab.Template;
            var routePrefix = method.Name;
            return routePrefix.ClearStringAffixes(affixes: AbandonActionAffixes);
        }

        /// <summary>
        /// 获取服务前缀
        /// </summary>
        /// <param name="fullname"></param>
        /// <returns></returns>
        public static string GetRoutePrefix(this Type routModuleType)
        {
            if (routModuleType == null) return "";
            var cab = routModuleType.GetCustomAttribute<RoutePrefixAttribute>();
            if (cab != null && !string.IsNullOrWhiteSpace(cab.Template))
                return cab.Template;
            return GetRoutePrefix(routModuleType.FullName);
        }

        /// <summary>
        /// 获取服务前缀
        /// </summary>
        /// <param name="fullname"></param>
        /// <returns></returns>
        public static string GetRoutePrefix(this string fullname)
        {
            if (string.IsNullOrWhiteSpace(fullname)) return fullname;
            var fn = fullname.Split('.');
            var path = fullname;
            if (fn.Length > 1)
            {
                path = fn[0].Trim('/') + "/" + (fn[fn.Length - 1].Trim('/')).GetControllerName();
            }
            return path;
        }
        /// <summary>
        /// 获取清除后缀的服务名称
        /// </summary>
        /// <param name="canme"></param>
        /// <returns></returns>
        public static string GetControllerName(this string canme)
        {
            return canme.ClearStringAffixes(affixes: AbandonControllerAffixes);
        }
        /// <summary>
        /// 获取动作方法请求谓词特性
        /// </summary>
        /// <param name="action">动作方法模型</param>
        public static string GetActionHttpMethod(this string actionMethod)
        {
            // 跳过已配置请求谓词特性的配置
            if (string.IsNullOrWhiteSpace(actionMethod)) return "POST";

            // 解析请求谓词
            var words = actionMethod.SplitCamelCase();
            var verbKey = words.First().ToLower();

            // 处理类似 getlist,getall 多个单词
            if (words.Length > 1 && Penetrates.VerbToHttpMethods.ContainsKey((words[0] + words[1]).ToLower()))
            {
                verbKey = (words[0] + words[1]).ToLower();
            }

            var verb = Penetrates.VerbToHttpMethods.ContainsKey(verbKey)
                ? Penetrates.VerbToHttpMethods[verbKey] ?? "POST" : "POST";

            return verb;
        }

        ///// <summary>
        ///// 是否是Api控制器
        ///// </summary>
        ///// <param name="type">type</param>
        ///// <returns></returns>
        //public static bool IsApiController(Type type)
        //{
        //    return IsApiControllerCached.GetOrAdd(type, Function);

        //    // 本地静态方法
        //    static bool Function(Type type)
        //    {
        //        // 不能是非公开、基元类型、值类型、抽象类、接口、泛型类
        //        if (!type.IsPublic || type.IsPrimitive || type.IsValueType || type.IsAbstract || type.IsInterface || type.IsGenericType) return false;

        //        // 继承 ControllerBase 或 实现 IDynamicApiController 的类型 或 贴了 [DynamicApiController] 特性
        //        if ((!typeof(Controller).IsAssignableFrom(type) && typeof(ControllerBase).IsAssignableFrom(type)) || typeof(IDynamicApiController).IsAssignableFrom(type) || type.IsDefined(typeof(DynamicApiControllerAttribute), true))
        //        {
        //            // 不是能被导出忽略的接口
        //            if (type.IsDefined(typeof(ApiExplorerSettingsAttribute), true) && type.GetCustomAttribute<ApiExplorerSettingsAttribute>(true).IgnoreApi) return false;

        //            return true;
        //        }
        //        return false;
        //    }
        //}
    }
}